﻿// -----------------------------------------------------------------------
// <copyright file="Words_SharpForth.cs" company="G.W. van der Vegt">
// SharpForth is inspired by JonesForthInC v1.48 and bb4wForth.
// </copyright>
// -----------------------------------------------------------------------

namespace SharpForth
{
    using System;
    using System.Diagnostics;
    using System.IO;
    using System.Linq;
    using System.Reflection;
    using System.Collections.Generic;
    using System.Threading;

    /// <summary>
    /// This static class contains all built-in Forth Words.
    /// </summary>
    public static partial class Words
    {
        #region SharpForth Specific Forth Words

        /// <summary>
        /// veg - non-standard.
        /// 
        /// Placeholder for Address 0.
        /// </summary>
        [WordName("XYYZ")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> XYYZ = new Lazy<DictionaryEntry>(
            () => new DictionaryEntry("XYYZ", Forth.FORTH_HIDDEN_MASK, delegate
            {
                Forth.DoOutput(Forth.ErrorMarker + "This Forth Word is reserved to protect Address 0");

                Forth.NEXT();
            }), true
            );

        /// <summary>
        /// veg - non-standard.
        /// 
        /// Just a dummy marker to instruct SEE to start ouputting the rest of the Forth Word as Mumeric Array.
        /// </summary>
        [WordName("DATA-MARKER")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> DATA_MARKER = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("DATA-MARKER", 0, delegate
             {
                 //! Just a marker for see to dump the rest as data.
             }), true);

        /// <summary>
        /// veg - non-standard.
        /// 
        /// Pushes the Depth of the RETURN STACK.
        /// </summary>
        [WordName("RDEPTH")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- depth ")]
        internal static Lazy<DictionaryEntry> RETURN_STACK_DEPTH = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("RDEPTH", 0, delegate
             {
                 Forth.PARAM_STACK.Push(Forth.RETURN_STACK.Count);

                 Forth.NEXT();
             }), true);

        /// <summary>
        /// veg - non-standard.
        /// 
        /// Print the Parameter Stack. Rightmost is TOS.
        /// </summary>
        [WordName(".STACK")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> PRINT_PARAM_STACK = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry(".STACK", 0, delegate
             {
                 Forth.DoOutput("( ", false);
                 foreach (Int32 val in Forth.PARAM_STACK.ToArray().Reverse())
                 {
                     Forth.DoOutput(String.Format("{0} ", val), false);
                 }
                 Forth.DoOutput(") ", false);

                 Forth.NEXT();
             }), true);

        /// <summary>
        /// veg - non-standard.
        /// 
        /// Print the Floating Point Stack.
        /// </summary>
        [WordName(".FSTACK")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> PRINT_FPARAM_STACK = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry(".FSTACK", 0, delegate
             {
                 Forth.DoOutput("( ", false);
                 foreach (Double fp in Forth.FPARAM_STACK.ToArray())
                 {
                     Forth.DoOutput(String.Format("{0} ", fp.ToString("E")), false);
                 }
                 Forth.DoOutput(") ", false);

                 Forth.NEXT();
             }), true);

        /// <summary>
        /// veg - non-standard.
        /// 
        /// Print the Syntax.
        /// </summary>
        [WordName("SYNTAX")]
        [WordSet(WordSets.SHARPFORTH)]
        [Depends("WORD")]
        [Depends("FIND")]
        [Syntax("<spaces>name ( -- )")]
        internal static Lazy<DictionaryEntry> PRINT_SYNTAX = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("SYNTAX", 0, delegate
             {
                 WORD.Value.Invoke();
                 FIND.Value.Invoke();

                 Int32 ndx = Forth.A2I(Forth.PARAM_STACK.Pop());

                 //! Skip Lookup if not a valid Word (it may be a number though).
                 Boolean match = ndx == -1;

                 if (!match)
                 {
                     String name = Forth.Dictionary[ndx].Name;
                     foreach (FieldInfo fi in typeof(Library).GetFields(BindingFlags.Public | BindingFlags.Static))
                     {
                         if (Forth.GetWordName(fi).Equals(name))
                         {
                             Forth.DoOutput((Forth.GetWordName(fi) + " " + Forth.GetSyntax(fi)).Trim(), false);
                             match = true;
                             break;
                         }
                     }
                 }

                 if (!match)
                 {
                     String name = Forth.Dictionary[ndx].Name;
                     foreach (FieldInfo fi in typeof(Words).GetFields(BindingFlags.NonPublic | BindingFlags.Static))
                     {
                         if (Forth.GetWordName(fi).Equals(name))
                         {
                             Forth.DoOutput((Forth.GetWordName(fi) + " " + Forth.GetSyntax(fi)).Trim(), false);
                             match = true;
                             break;
                         }
                     }
                 }

                 if (!match)
                 {
                     Forth.DoOutput("( n/a ) ", false);
                 }

                 Forth.NEXT();
             }), true);

        /// <summary>
        /// veg - non-standard.
        /// 
        /// Prints a list of files.
        /// </summary>
        [WordName("LIST-FILES")]
        [WordSet(WordSets.SHARPFORTH)]
        [Depends("WORD")]
        [Syntax("( addr len -- 0 if success, -1 if fail )")]
        internal static Lazy<DictionaryEntry> LIST_FILES = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("LIST-FILES", 0, delegate
             {
                 WORD.Value.Invoke();

                 Int32 length = Forth.POP_P_STACK();
                 Int32 start = Forth.POP_P_STACK();

                 // Look up in the dictionary.
                 String dn = Forth.FetchWord(start, length).Trim('\"').Trim('\'');

                 if (!String.IsNullOrEmpty(dn) && Directory.Exists(dn))
                 {
                     List<String> dirs = Directory.EnumerateFiles(dn).ToList();

                     Forth.DoOutput(String.Format("Listing {0} files\r", dirs.Count), true);
                     Forth.DoOutput("", true);

                     foreach (String dir in dirs)
                     {
                         if (dir.StartsWith(dn + Path.DirectorySeparatorChar))
                         {
                             Forth.DoOutput(String.Format(" {0}", dir.Remove(0, (dn + Path.DirectorySeparatorChar).Length)), true);
                         }
                         else
                         {
                             Forth.DoOutput(String.Format(" {0}", dir), true);
                         }
                     }
                     Forth.DoOutput("", true);
                     Forth.PUSH_P_STACK(Forth.FORTH_TRUE);
                 }
                 else
                 {
                     Forth.DoOutput(Forth.ErrorMarker + String.Format("Directory '{0}' not found.", dn), true);
                     Forth.PUSH_P_STACK(Forth.FORTH_FALSE);
                 }

                 Forth.NEXT();
             }), true);

        /// <summary>
        /// veg - non-standard.
        /// 
        /// Load a File into the input Queue.
        /// </summary>
        [WordName("LOAD-FILE")]
        [WordSet(WordSets.SHARPFORTH)]
        [Depends("WORD")]
        [Syntax("( addr len -- 0 if success, -1 if fail )")]
        internal static Lazy<DictionaryEntry> LOAD_FILE = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("LOAD-FILE", 0, delegate
             {
                 WORD.Value.Invoke();

                 Int32 length = Forth.POP_P_STACK();
                 Int32 start = Forth.POP_P_STACK();

                 // Look up in the dictionary.
                 String fn = Forth.FetchWord(start, length).Trim('\"').Trim('\'');

                 if (!String.IsNullOrEmpty(fn) && File.Exists(fn))
                 {
                     String src = File.ReadAllText(fn);

                     Forth.DoOutput(String.Format("Reading {0} characters", src.Length), true);

                     foreach (Char ch in src)
                     {
                         if (ch != '\r')
                         {
                             Forth.input.Enqueue(ch);
                         }
                         else
                         {
                             Forth.input.Enqueue('\n');
                         }
                     }

                     if (!src.EndsWith("\n"))
                     {
                         Forth.input.Enqueue('\n');
                     }

                     //": LOAD-FILE ( addr len -- 0 if success, -1 if fail)
                     Forth.PUSH_P_STACK(Forth.FORTH_TRUE);
                 }
                 else
                 {
                     Forth.DoOutput(Forth.ErrorMarker + String.Format("File '{0}' not found.", fn), true);
                     Forth.PUSH_P_STACK(Forth.FORTH_FALSE);
                 }

                 Forth.NEXT();
             }), true);

        /// <summary>
        /// veg - non-standard.
        /// 
        /// Load a Url into the input Queue.
        /// </summary>
        [WordName("LOAD-URL")]
        [WordSet(WordSets.SHARPFORTH)]
        [Depends("WORD")]
        [Syntax("( addr len -- 0 if success, -1 if fail )")]
        internal static Lazy<DictionaryEntry> LOAD_URL = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("LOAD-URL", 0, delegate
             {
                 WORD.Value.Invoke();

                 Int32 length = Forth.POP_P_STACK();
                 Int32 start = Forth.POP_P_STACK();

                 // Look up in the dictionary.
                 String url = Forth.FetchWord(start, length).Trim('\"').Trim('\'');

                 if (!String.IsNullOrEmpty(url) && Uri.IsWellFormedUriString(url, UriKind.Absolute))
                 {
                     String src = Forth.GetWebPage(new Uri(url));

                     Forth.DoOutput(String.Format("Reading {0} characters", src.Length), true);

                     foreach (Char ch in src)
                     {
                         if (ch != '\r')
                         {
                             Forth.input.Enqueue(ch);
                         }
                         else
                         {
                             Forth.input.Enqueue('\n');
                         }
                     }

                     if (!src.EndsWith("\n"))
                     {
                         Forth.input.Enqueue('\n');
                     }

                     //": LOAD-FILE ( addr len -- 0 if success, -1 if fail)
                     Forth.PUSH_P_STACK(Forth.FORTH_TRUE);
                 }
                 else
                 {
                     Forth.DoOutput(Forth.ErrorMarker + String.Format("Url '{0}' not found.", url), true);
                     Forth.PUSH_P_STACK(Forth.FORTH_FALSE);
                 }

                 Forth.NEXT();
             }), true);

        [WordName("TRACE")]
        [WordSet(WordSets.SHARPFORTH)]
        [Depends("DOCOL")]
        [Depends("LIT")]
        [Depends("BRANCH")]
        [Depends("EXIT")]
        [Syntax("( -- adr )")]
        internal static Lazy<DictionaryEntry> TRACE = new Lazy<DictionaryEntry>(
                () => new DictionaryEntry("TRACE", 0, new Int32[]
                {
                     Forth.Locate("DOCOL"),

                     Forth.Locate("LIT"),
    
                    //! 24 is 6 words (4*6 bytes) ahead, points to BASE Below, 
                    //! This address Will pe pushed on the PARAM_STACK.
                    ((Forth.Dictionary.IndexOf(Forth.Dictionary.Last()) + 1) << 16) + 24,

                    //! Jump over the LIT BASE
                    Forth.Locate("BRANCH"),
                    12,

                    //! The actual Storage and Initial Value.
                    Forth.Locate("LIT"),
                    Forth.TRACE ? Forth.FORTH_TRUE:Forth.FORTH_FALSE,
                      
                    Forth.Locate("EXIT")
                }), true);

        [WordName("TRACEON")]
        [WordSet(WordSets.SHARPFORTH)]
        [Depends("DOCOL")]
        [Depends("LIT")]
        [Depends("BRANCH")]
        [Depends("EXIT")]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> TRACEON = new Lazy<DictionaryEntry>(
                () => new DictionaryEntry("TRACEON", 0, new Int32[]
                {
                    Forth.Locate("DOCOL"),

                    Forth.Locate("LIT"),
                    Forth.FORTH_TRUE,
                    
                    Forth.Locate("TRACE"),
                    Forth.Locate("!"),

                    Forth.Locate("EXIT")
                }), true);

        [WordName("TRACEOFF")]
        [WordSet(WordSets.SHARPFORTH)]
        [Depends("DOCOL")]
        [Depends("LIT")]
        [Depends("BRANCH")]
        [Depends("EXIT")]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> TRACEOFF = new Lazy<DictionaryEntry>(
                () => new DictionaryEntry("TRACEOFF", 0, new Int32[]
                {
                    Forth.Locate("DOCOL"),

                    Forth.Locate("LIT"),
                    Forth.FORTH_FALSE,
                    
                    Forth.Locate("TRACE"),
                    Forth.Locate("!"),

                    Forth.Locate("EXIT")
                }), true);

        /// <summary>
        /// 1436 ( --- SHARPFORTH_VERSION)
        /// </summary>
        [WordName("VERSION")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> VERSION = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("VERSION", 0, delegate
             {
                 Forth.PARAM_STACK.Push(100 * Forth.SharpForthVersion.Major +
                     Forth.SharpForthVersion.Revision);

                 Forth.NEXT();
             }), true);

        /// <summary>
        /// 1438 ( --- F_IMMED)
        /// </summary>
        [WordName("F_IMMED")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> F_IMMED = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("F_IMMED", 0, delegate
             {
                 Forth.PARAM_STACK.Push(Forth.FORTH_IMMED_MASK);

                 Forth.NEXT();
             }), true);

        /// <summary>
        /// 1439 ( --- F_HIDDEN)
        /// </summary>
        [WordName("F_HIDDEN")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> F_HIDDEN = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("F_HIDDEN", 0, delegate
             {
                 Forth.PARAM_STACK.Push(Forth.FORTH_HIDDEN_MASK);

                 Forth.NEXT();
             }), true);

        /// <summary>
        /// Used instead of HEADER.
        /// 
        /// Words not starting with DOCOL push their address instead of being executed.
        /// </summary>
        [WordName("(CREATE)")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( \"spaces<name>\" -- )")]
        internal static Lazy<DictionaryEntry> PAREN_CREATE = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("(CREATE)", Forth.FORTH_HIDDEN_MASK, delegate
             {
                 //! Excpect a STRING_BUFFER Pointer.
                 Int32 length = Forth.POP_P_STACK();
                 Int32 start = Forth.POP_P_STACK() & Forth.MTM;

                 String name = Forth.FetchWord(start, length, true);

                 Forth.Dictionary.Add(new DictionaryEntry(name, 0));

                 Forth.LATEST = Forth.I2A(Forth.Dictionary.Count - 1);

                 Forth.DP = Forth.LATEST + (Forth.Dictionary[Forth.A2I(Forth.LATEST)].Definition.Count << 2) | Forth.MEM_DEF;
             }), true);

        /// <summary>
        /// 5160
        /// </summary>
        [WordName("WELCOME")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> WELCOME = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("WELCOME", 0, delegate
             {
                 Forth.DoOutput(String.Empty, true);
                 Forth.DoOutput(" · Welcome to SharpForth !", true);
                 Forth.DoOutput(String.Empty, true);
                 Forth.DoOutput(String.Format(" · Version: v{0}", Forth.SharpForthVersion), true);
                 Forth.DoOutput(String.Empty, true);
                 Forth.DoOutput(" · SharpForth is a managed Forth written in 100% C# without assembly code.", true);
                 Forth.DoOutput(" · SharpForth is inspired from JonesForth, JonesForthInC and bb4wForth.", true);
                 Forth.DoOutput(" · SharpForth can be found at http://sharpforth.codeplex.com/", true);
                 Forth.DoOutput(String.Empty, true);
             }), true);

        /// <summary>
        /// 4218
        /// </summary>
        [WordName("(SEE)")]
        [WordSet(WordSets.SHARPFORTH)]
        [Depends("LIT")]
        [Depends("EXIT")]
        [Depends("BRANCH")]
        [Depends("0BRANCH")]
        [Depends("LITSTRING")]
        [Depends("DATA-MARKER")]
        [Depends("[']")]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> PAREN_SEE = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("(SEE)", Forth.FORTH_HIDDEN_MASK, delegate
             {
                 Int32 loc = Forth.PARAM_STACK.Pop();

                 if (loc == -1)
                 {
                     // Forth.DoOutput(Forth.ErrorMarker + "Definition of Word could not found be located.", true);

                     Forth.NEXT();

                     return;
                 }

                 DictionaryEntry entry = Forth.Dictionary[Forth.A2I(loc)];

                 if (!entry.IsSharpCode)
                 {
                     Int32 i = 0;
                     String numerical;

                     if (entry.Definition.Count != 0 && Forth.Dictionary[Forth.A2I(entry.Definition[0])].Name.Equals(Words.DOCOL.Value.Name))
                     {
                         while (i < entry.Definition.Count)
                         {
                             Int32 ndx = Forth.A2I(entry.Definition[i]);

                             if (Forth.Dictionary[ndx].Name.Equals(Words.DOCOL.Value.Name))
                             {
                                 Forth.DoOutput(": {0} ", entry.Name);
                                 if ((entry.Flags & Forth.FORTH_IMMED_MASK) == Forth.FORTH_IMMED_MASK)
                                 {
                                     Forth.DoOutput("{0} ", "IMMEDIATE");
                                 }
                             }
                             else if (Forth.Dictionary[ndx].Name.Equals(Words.LIT.Value.Name))
                             {
                                 i++;

                                 Forth.DecimalToBase(entry.Definition[i], Forth.BASE, out numerical);

                                 Forth.DoOutput("{0} ", Forth.NumericPrefix(numerical, Forth.BASE));
                             }
                             else if (Forth.Dictionary[ndx].Name.Equals(Words.EXIT.Value.Name))
                             {
                                 if (i != entry.Definition.Count - 1)
                                 {
                                     //! Only Dump when not at the end.
                                     Forth.DoOutput("{0} ", Forth.Dictionary[ndx].Name);
                                 }
                             }
                             else if (Forth.Dictionary[ndx].Name.Equals(Words.BRANCH.Value.Name))
                             {
                                 Forth.DoOutput("{0} ", Forth.Dictionary[ndx].Name);

                                 i++;

                                 Forth.DecimalToBase(entry.Definition[i], Forth.BASE, out numerical);
                                 Forth.DoOutput("( {0} ) ", Forth.NumericPrefix(numerical, Forth.BASE));
                             }
                             else if (Forth.Dictionary[ndx].Name.Equals(Words.ZBRANCH.Value.Name))
                             {
                                 Forth.DoOutput("{0} ", Forth.Dictionary[ndx].Name);

                                 i++;

                                 Forth.DecimalToBase(entry.Definition[i], Forth.BASE, out numerical);
                                 Forth.DoOutput("( {0} ) ", Forth.NumericPrefix(numerical, Forth.BASE));
                             }
                             else if (Forth.Dictionary[ndx].Name.Equals(Words.PAREN_LOOP.Value.Name))
                             {
                                 Forth.DoOutput("{0} ", Forth.Dictionary[ndx].Name);

                                 i++;

                                 Forth.DecimalToBase(entry.Definition[i], Forth.BASE, out numerical);
                                 Forth.DoOutput("( {0} ) ", Forth.NumericPrefix(numerical, Forth.BASE));
                             }
                             else if (Forth.Dictionary[ndx].Name.Equals(Words.PAREN_PLUS_LOOP.Value.Name))
                             {
                                 Forth.DoOutput("{0} ", Forth.Dictionary[ndx].Name);

                                 i++;

                                 Forth.DecimalToBase(entry.Definition[i], Forth.BASE, out numerical);
                                 Forth.DoOutput("( {0} ) ", Forth.NumericPrefix(numerical, Forth.BASE));
                             }
                             else if (Forth.Dictionary[ndx].Name.Equals(Words.LITSTRING.Value.Name) ||
                                      Forth.Dictionary[ndx].Name.Equals(Words.PAREN_ABORT_QUOTE.Value.Name))
                             {
                                 if (Forth.Dictionary[ndx].Name.Equals(Words.PAREN_ABORT_QUOTE.Value.Name))
                                 {
                                     Forth.DoOutput("ABORT\"", false);
                                 }
                                 else
                                 {
                                     Forth.DoOutput("\"", false);
                                 }

                                 i++;

                                 Int32 len = entry.Definition[i];

                                 i++;

                                 for (Int32 j = 0; j < len; j++)
                                 {
                                     using (Int32ByteUnion union = new Int32ByteUnion(entry.Definition[i + (j >> 2)]))
                                     {
                                         Forth.DoOutput("{0}", (Char)union[j % 4]);
                                     }
                                 }

                                 i += len >> 2;

                                 Forth.DoOutput("\" ", false);
                             }
                             else if (Forth.Dictionary[ndx].Name.Equals(Words.BRACKET_TICK.Value.Name))
                             {
                                 i++;

                                 Forth.DoOutput("['] {0} ", Forth.Dictionary[Forth.A2I(entry.Definition[i])].Name);
                             }
                             else if (Forth.Dictionary[ndx].Name.Equals(Words.DATA_MARKER.Value.Name))
                             {
                                 i++;

                                 Forth.DoOutput("[ ");
                                 while (i < entry.Definition.Count)
                                 {
                                     Forth.DecimalToBase(entry.Definition[i++], Forth.BASE, out numerical);
                                     Forth.DoOutput("{0} ", Forth.NumericPrefix(numerical, Forth.BASE));
                                 }
                                 Forth.DoOutput("] ");
                             }
                             else
                             {
                                 Forth.DoOutput("{0} ", Forth.Dictionary[ndx].Name);
                             }

                             i++;
                         }
                     }
                     else
                     {
                         Forth.DoOutput("[ ");
                         while (i < entry.Definition.Count)
                         {
                             Forth.DecimalToBase(entry.Definition[i++], Forth.BASE, out numerical);
                             Forth.DoOutput("{0} ", Forth.NumericPrefix(numerical, Forth.BASE));
                         }
                         Forth.DoOutput("] ");
                     }
                 }
                 else
                 {
                     Forth.DoOutput("( {0} ) ", "C# Code");
                 }

                 Forth.DoOutput(";", true);

                 Forth.NEXT();
             }), true);

        /// <summary>
        /// Flush input Queue.
        /// </summary>
        [WordName("FLUSH")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- )")]
        internal static Lazy<DictionaryEntry> FLUSH = new Lazy<DictionaryEntry>(
             () => new DictionaryEntry("FLUSH", 0, delegate
             {
                 Forth.input.Clear();
             }), true);

        /// <summary>
        /// Returns the number of mSec elapsed since the SharpForth start.
        /// </summary>
        [WordName("ELAPSED")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- n )")]
        internal static Lazy<DictionaryEntry> ELAPSED = new Lazy<DictionaryEntry>(
              () => new DictionaryEntry("ELAPSED", 0, delegate
              {
                  DateTime val = DateTime.Now;

                  //! Check for Overflow!
                  Forth.PUSH_P_STACK((Int32)((val.Ticks - Forth.START_TICKS) / 10000));

              }), true);

        /// <summary>
        /// Returns the Terminal Width.
        /// </summary>
        [WordName("TERM-WIDTH")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- n )")]
        internal static Lazy<DictionaryEntry> TERM_WIDTH = new Lazy<DictionaryEntry>(
              () => new DictionaryEntry("TERM-WIDTH", 0, delegate
              {
                  Forth.PUSH_P_STACK(Forth.TerminalWidth);

              }), true);

        /// <summary>
        /// Returns the Terminal Height.
        /// </summary>
        [WordName("TERM-HEIGHT")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- n )")]
        internal static Lazy<DictionaryEntry> TERM_HEIGHT = new Lazy<DictionaryEntry>(
              () => new DictionaryEntry("TERM-HEIGHT", 0, delegate
              {
                  Forth.PUSH_P_STACK(Forth.TerminalHeight);

              }), true);

        /// <summary>
        /// Pushes PI onto the FP Stack.
        /// </summary>
        [WordName("PI")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( F: -- r )")]
        internal static Lazy<DictionaryEntry> PI = new Lazy<DictionaryEntry>(
              () => new DictionaryEntry("PI", 0, delegate
              {
                  Forth.PUSH_F_STACK(Math.PI);

              }), true);

        /// <summary>
        /// Pushes E onto the FP Stack.
        /// </summary>
        [WordName("E")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( F: -- r )")]
        internal static Lazy<DictionaryEntry> E = new Lazy<DictionaryEntry>(
              () => new DictionaryEntry("E", 0, delegate
              {
                  Forth.PUSH_F_STACK(Math.E);
              }), true);

        /// <summary>
        /// Adds %TEMP% to the String Buffer and leaves a addr + length.
        /// </summary>
        [WordName("$TEMP")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- c-addr u )")]
        internal static Lazy<DictionaryEntry> ENV_TEMP = new Lazy<DictionaryEntry>(
              () => new DictionaryEntry("$TEMP", 0, delegate
              {
                  Int32 WORD_BUFFER_START = Forth.STRING_BUFFER.Count;

                  foreach (Char key in Environment.GetEnvironmentVariable("TEMP"))
                  {
                      Forth.STRING_BUFFER.Add(key);
                  }

                  Forth.PARAM_STACK.Push(WORD_BUFFER_START | Forth.MEM_WRD);
                  Forth.PARAM_STACK.Push(Forth.STRING_BUFFER.Count - WORD_BUFFER_START);
              }), true);

        /// <summary>
        /// Adds %HOMEDRIVE%\%HOMEPATH% to the String Buffer and leaves a addr + length.
        /// </summary>
        [WordName("$HOME")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- c-addr u )")]
        internal static Lazy<DictionaryEntry> ENV_HOMEDIR = new Lazy<DictionaryEntry>(
              () => new DictionaryEntry("$HOME", 0, delegate
              {
                  Int32 WORD_BUFFER_START = Forth.STRING_BUFFER.Count;

                  foreach (Char key in Environment.GetEnvironmentVariable("HOMEDRIVE") + Environment.GetEnvironmentVariable("HOMEPATH"))
                  {
                      Forth.STRING_BUFFER.Add(key);
                  }

                  Forth.PARAM_STACK.Push(WORD_BUFFER_START | Forth.MEM_WRD);
                  Forth.PARAM_STACK.Push(Forth.STRING_BUFFER.Count - WORD_BUFFER_START);
              }), true);

        /// <summary>
        /// Adds %OS% to the String Buffer and leaves a addr + length.
        /// </summary>
        [WordName("$OS")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( -- c-addr u )")]
        internal static Lazy<DictionaryEntry> O_S = new Lazy<DictionaryEntry>(
              () => new DictionaryEntry("$OS", 0, delegate
              {
                  Int32 WORD_BUFFER_START = Forth.STRING_BUFFER.Count;

                  foreach (Char key in Environment.GetEnvironmentVariable("OS"))
                  {
                      Forth.STRING_BUFFER.Add(key);
                  }

                  Forth.PARAM_STACK.Push(WORD_BUFFER_START | Forth.MEM_WRD);
                  Forth.PARAM_STACK.Push(Forth.STRING_BUFFER.Count - WORD_BUFFER_START);
              }), true);

        /// <summary>
        /// Prints the String at the top of the stack.
        /// </summary>
        [WordName("PEEK\"")]
        [WordSet(WordSets.SHARPFORTH)]
        [Syntax("( c-addr u -- c-addr u )")]
        internal static Lazy<DictionaryEntry> PEEK_SLASH = new Lazy<DictionaryEntry>(
              () => new DictionaryEntry("PEEK\"", 0, delegate
              {
                  Int32 cnt = Forth.POP_P_STACK();
                  Int32 src = Forth.POP_P_STACK();

                  String s = String.Empty;

                  for (Int32 i = 0; i < cnt; i++)
                  {
                      Int32 adr1 = src + i;
                      switch (Forth.A2M(adr1))
                      {
                          case Forth.MEM_DEF:
                              s += (Char)new Int32ByteUnion(Forth.Dictionary[Forth.A2I(adr1)].Definition[Forth.A2D(adr1)])[adr1 % 4];
                              break;
                          case Forth.MEM_RSP:
                              Forth.DoOutput("MemoryType 1 Not Implemented");
                              return;
                          case Forth.MEM_PRM:
                              Forth.DoOutput("MemoryType 2 Not Implemented");
                              return;
                          case Forth.MEM_WRD:
                              s += (Char)Forth.STRING_BUFFER[Forth.A2A(adr1)];
                              break;
                      }
                  }

                  Forth.DoOutput(String.Format("{0} {1} - \"{2}\"", src, cnt, s), true);

                  Forth.PUSH_P_STACK(src);
                  Forth.PUSH_P_STACK(cnt);
              }), true);

        #endregion SharpForth Specific Forth Words
    }
}
